<?php
/**
*	@author SignpostMarv Martin
*	@package UHU
*	@subpackage UHU_Loadable
*/

/**
*	Exception class thrown by uhu_loadable
*	@package UHU_exception
*	@subpackage UHU_Loadable
*/
class uhu_loadable_exception extends uhu_exception
{
	protected function getExtendedMessage($code=null)
	{
		$message = '%s';
		switch($code)
		{
			case 100: # File the loadable is meant to be found in does not exist
			case 101: # class or interface specified in loadable has invalid name
				$message = 'Could not build loadable: %s'; 
			break;
			case 200: # class or interfaces specified in loadable not found in specified file
			case 201: # class or interface specified in loadable declared prior to loading
			case 202: # specified loadable not registered
			case 203: # no loadables registered at all
				$message = 'Could not load loadable: %s';
			break;
			case 300: # loadable already registered
				$message = 'Cannot register loadable: %s';
			break;
		}
		return $message;
	}
}

/**
*	The basic class used to define applications, components and libraries used within UHU
*	@package UHU
*	@subpackage UHU_Loadable
*/
class uhu_loadable
{
/**
*	@var array the array storing the loadable definitions in memory.
*/
	protected static $components = array();
/**
*	@var string The location of the loadable
*/
	protected $path;
/**
*	@var string A human-readable label for the loadable
*/
	protected $label;
/**
*	@var string the name of a class that will be found in the loadable
*/
	protected $class_name;
/**
*	@var bool TRUE if the loadable refers to an interface, FALSE if if the loadable refers to a class or abstract class
*/
	protected $interface;
/**
*	@var bool set to TRUE if a loadable has been loaded, FALSE otherwise
*/
	protected $loaded = false;
/**
*	@var bool set to FALSE while a loadable is loading, TRUE once it has finished loading.
*/
	protected $loading = false;
/**
*	builds an UHU Loadable
*	@uses uhu_loadable_exception if the loadable $path_to_file doesn't exist, or if the $class_name is invalid.
*	@param string $path_to_file The location of the loadable
*	@param string $label A human-readable label for the loadable
*	@param string $class_name the name of a class that will be found in the loadable
*	@param bool $interface TRUE if the loadable refers to an interface, FALSE if if the loadable refers to a class or abstract class
*/
	final public function __construct($path_to_file,$label,$class_name,$interface=false)
	{
		if(file_exists($path_to_file) === false)
		{
			throw new uhu_loadable_exception('File does not exist: ' . $path_to_file,100);
		}
		else if(substr_count($class_name,' ') > 0 || substr_count($class_name,'-') > 0)
		{
			throw new uhu_loadable_exception('Specified ' . ($interface ? 'Interface' : 'Class') . ' has invalid name',101);
		}
		else
		{
			$this->path = $path_to_file;
			$this->label = $label;
			$this->class_name = $class_name;
			$this->interface = $interface;
		}
	}
/**
*	@return string
*	@uses uhu_loadable::$path
*/
	final public function path()
	{
		return $this->path;
	}
/**
*	@return string
*	@uses uhu_loadable::$label
*/
	final public function label()
	{
		return $this->label;
	}
/**
*	@return string
*	@uses uhu_loadable::$class_name
*/
	final public function class_name()
	{
		return $this->class_name;
	}
/**
*	@return bool TRUE if the class/inteface exists, FALSE otherwise
*	@uses uhu_loadable::$interface
*/
	protected function load_cond()
	{
		return $this->interface ? interface_exists($this->class_name,false) : class_exists($this->class_name,false);
	}
/**
*	Loads the loadable, throwing an Exception upon failure
*	@see uhu_loadable::__construct()
*	@uses uhu_loadable::$loaded
*	@uses uhu_loadable::load_cond()
*	@uses uhu_loadable::$loading
*	@uses uhu_loadable::$path
*	@uses uhu_loadable::$inteface
*	@uses uhu_loadable::$class_name
*	@uses uhu_loadable_exception
*/
	final public function load()
	{
		if($this->loaded === false)
		{
			if($this->load_cond() === false && $this->loading === false)
			{
				$this->loading = true;
				require_once($this->path);
				if($this->load_cond() === false)
				{
					$msg = $this->interface ? 'Interface' : 'Class';
					throw new uhu_loadable_exception($msg . '\'' . $this->class_name . '\' not found in file \'' . $this->path . '\'',200);
				}
				else
				{
					$this->loaded = true;
				}
			}
			else if($this->loading === false)
			{
				throw new uhu_loadable_exception('Class \'' . $this->class_name . '\' existed before loading attempt.',201);
			}
		}
	}
}

/**
*	@package UHU_Loadable
*	@subpackage UHU_Components
**/
class uhu_component extends uhu_loadable{
	const short_type = 'component';
	const full_type  = 'Component';
	const plural     = 'Components';
}

/**
*	@package UHU_Loadable
*	@subpackage UHU_Apps
**/
class uhu_application extends uhu_loadable{
	const short_type = 'app';
	const full_type  = 'Application';
	const plural     = 'Applications';
}

/**
*	@package UHU_Loadable
*	@subpackage UHU_Libs
**/
class uhu_lib extends uhu_loadable{
	const short_type = 'lib';
	const full_type  = 'Library';
	const plural     = 'Libraries';
}
?>